import {
    _decorator,
    Component,
    EventKeyboard,
    Input,
    input,
    KeyCode,
    v3,
} from 'cc';
const { ccclass, property } = _decorator;

@ccclass('KeyMove')
export class KeyMove extends Component {
    @property
    speed: number = 100;

    protected onLoad(): void {
        input.on(Input.EventType.KEY_DOWN, this.onKeyDown, this);
        input.on(Input.EventType.KEY_UP, this.onKeyUp, this);
    }

    // 当前按下的方向键栈，存储keyCode，后进先出
    private keyStack: KeyCode[] = [];
    // 当前移动方向
    moveDir = v3(0, 0, 0);

    onKeyDown(e: EventKeyboard) {
        // 只处理方向键
        if (!this.isDirectionKey(e.keyCode)) return;
        // 如果已在栈中，先移除再推入，保证顺序
        const idx = this.keyStack.indexOf(e.keyCode);
        if (idx !== -1) this.keyStack.splice(idx, 1);
        this.keyStack.push(e.keyCode);
        this.updateMoveDir();
    }

    onKeyUp(e: EventKeyboard) {
        if (!this.isDirectionKey(e.keyCode)) return;
        const idx = this.keyStack.indexOf(e.keyCode);
        if (idx !== -1) this.keyStack.splice(idx, 1);
        this.updateMoveDir();
    }

    private isDirectionKey(keyCode: KeyCode) {
        return (
            keyCode === KeyCode.KEY_W ||
            keyCode === KeyCode.KEY_A ||
            keyCode === KeyCode.KEY_S ||
            keyCode === KeyCode.KEY_D
        );
    }

    private updateMoveDir() {
        if (this.keyStack.length === 0) {
            this.moveDir = v3(0, 0, 0);
            return;
        }
        const key = this.keyStack[this.keyStack.length - 1];
        switch (key) {
            case KeyCode.KEY_W:
                this.moveDir = v3(0, 1, 0);
                break;
            case KeyCode.KEY_S:
                this.moveDir = v3(0, -1, 0);
                break;
            case KeyCode.KEY_A:
                this.moveDir = v3(-1, 0, 0);
                break;
            case KeyCode.KEY_D:
                this.moveDir = v3(1, 0, 0);
                break;
        }
    }
    start() {}

    update(deltaTime: number) {
        if (this.moveDir.equals(v3(0, 0, 0))) {
            return;
        }
        this.node.setPosition(
            this.node.position.add(
                v3(
                    this.moveDir.x * this.speed * deltaTime,
                    this.moveDir.y * this.speed * deltaTime,
                    0,
                ),
            ),
        );
    }
}
